home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / pine / ccmd / wild.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-08-19  |  6.4 KB  |  238 lines

  1. /*
  2.  Author: Howie Kaye
  3.  
  4.  Columbia University Center for Computing Activities, July 1986.
  5.  Copyright (C) 1986, 1987, Trustees of Columbia University in the City
  6.  of New York.  Permission is granted to any individual or institution
  7.  to use, copy, or redistribute this software so long as it is not sold
  8.  for profit, provided this copyright notice is retained.
  9. */
  10.  
  11. #define TRUE 1
  12. #define FALSE 0
  13. #define NULL 0
  14.  
  15. #ifdef MSDOS
  16. #include <ctype.h>
  17. #define uncase(x) tolower(x)        /* XXX */
  18. #else
  19. #define uncase(x) (x)
  20. #endif
  21.  
  22. /*
  23.  * pattern matcher.
  24.  * matches patterns with wildcards of:
  25.  * '*' = matches any string
  26.  * '?' = any char
  27.  * '[abc-h]' = any include character or range
  28.  * '{abc,def}' = any included string.  these may include any other wildcard
  29.  */
  30. static
  31. match(pattern,string) char *pattern,*string; {
  32.   char *psave,*ssave;            /* back up pointers for failure */
  33.   psave = ssave = NULL;            /* initially no value */
  34.   while (1) {                /* skip first */
  35.     for (; uncase(*pattern) == uncase(*string); pattern++,string++)  
  36.       if (*string == '\0') {        /* end of strings, succeed */
  37.     return(1);
  38.       }
  39.     if ((*string != '\0') && (*pattern == '{')) { /* a "{"...try to match it */
  40.       if (do_curly(pattern,&string)) {    /* the curly routine checks the rest */
  41.     return(TRUE);            /* of the string too */
  42.       }
  43.       else {
  44.     if (ssave != NULL && *ssave != '\0') { /* if not at end  */
  45.                     /* ...have seen a star */
  46.       string = ++ssave;        /* skip 1 char from string */
  47.       pattern = psave;        /* and back up pattern */
  48.     }
  49.     else {
  50.       return(0);            /* '{' didn't match.   fail. */
  51.     }
  52.       }
  53.     }
  54.     else if ((*string != '\0') && (*pattern == '[')) { /* a '[' */
  55.       if (do_list(*string,pattern)) {    /* try to match the list */
  56.     while (*pattern != ']' && *pattern != '\0') { /* and skip past it */
  57.       pattern++;
  58.     } 
  59.     if (*pattern == ']') pattern++;
  60.     ++string;            /* and the string */
  61.       }
  62.       else {
  63.     if (ssave != NULL && *ssave != '\0') { /* if not at end  */
  64.                     /* ...have seen a star */
  65.       string = ++ssave;        /* skip 1 char from string */
  66.       pattern = psave;        /* and back up pattern */
  67.     }
  68.     else {
  69.       return(0);            /* no match.  fail */
  70.     }
  71.       }
  72.     } else if (*string != '\0' && *pattern == '?') {
  73.       ++pattern;            /* '?', let it match */
  74.       ++string;
  75.     } else if (*pattern == '*') {    /* '*' ... */
  76.         psave = ++pattern;        /* remember where we saw it */
  77.         ssave = string;            /* let it match 0 chars */
  78.     } else if (ssave != NULL && *ssave != '\0') { /* if not at end  */
  79.                     /* ...have seen a star */
  80.       string = ++ssave;            /* skip 1 char from string */
  81.       pattern = psave;            /* and back up pattern */
  82.     } else {
  83.         return(0);            /* otherwise just fail */
  84.     }
  85.   }
  86. }
  87.  
  88.  
  89. char *nextchr();
  90.  
  91. /*
  92.  * match patterns in square brackets
  93.  */
  94. static
  95. do_list(chr,pattern) char chr, *pattern; {
  96.   int inverse = 0;            /* test if a "not'ed" pattern */
  97.   int match=0;
  98.   int range[128],i,checked;
  99.   char lower, upper;
  100.  
  101.   for (i = 0; i < 128; i++) range[i] = 0;
  102.   pattern++;                /* pass '[' */
  103.   if (*pattern == '^') {        /* check for negation */
  104.     inverse = TRUE;
  105.     pattern++;                /* and skip past it */
  106.   }
  107.   
  108.   while(*pattern != ']' && *pattern != '\0') {
  109.     pattern = nextchr(pattern,&lower,&upper); /* fill in chars */
  110.     for(i = uncase(lower); i <= uncase(upper); i++){/* over possible ranges */
  111.       range[i] = 1;
  112.     }
  113.     pattern++;
  114.   }
  115.   return(inverse ^ range[uncase(chr)]);    /* return match based on inverse */
  116. }
  117.  
  118. /*
  119.  * get next range of chars out of bracket'ed list
  120.  * returns upper and lower bound in lower and upper
  121.  * if not a range, lower == upper
  122.  */
  123.  
  124. static
  125. char *
  126. nextchr(pattern,lower,upper) char *pattern; char *lower,*upper; {
  127.   if (*pattern == '\\') {        /* a quoted char */
  128.     pattern++;
  129.   }
  130.   *lower = *pattern;            /* get first char */
  131.   *upper = *lower;            /* assume not a range */
  132.   if (pattern[1] == '-') {        /* wrong. */
  133.     pattern+=2;                /* skip the dash. */
  134.     if (*pattern == '\\') {        /* check for quote again */
  135.       pattern++;
  136.     }
  137.     *upper = *pattern;            /* get the upper limit */
  138.   }
  139.   return(pattern);            /* return updated pattern pointer */
  140. }
  141.  
  142. char *get_curly_token();
  143.  
  144. /*
  145.  * match inside curly braces
  146.  */
  147.  
  148. do_curly(pattern,string) char *pattern,**string; {
  149.   char current[300],*p;        /* big buffer,  */
  150.   int last = FALSE;
  151.   int complete;
  152.   int count;
  153.   int maxlen;
  154.  
  155.   count = 0;
  156.   pattern++;
  157.   maxlen = 0;
  158.   while(1) {                /* get next token from in braces */
  159.     pattern = get_curly_token(pattern,current);
  160.     if (match(current,*string)) {    /* if a match return success */
  161.       return(TRUE);
  162.     }
  163.     if (*pattern == '\0' || *pattern == '}') /* otherwise, keep */
  164.       break;
  165.     pattern++;                /* going to next token */
  166.   }
  167.   return(FALSE);            /* failure */
  168. }
  169.  
  170. /*
  171.  * get the next token in curly braces, and append the end of the string 
  172.  * to it.
  173.  */
  174. char *
  175. get_curly_token(pattern,current) char *pattern,*current; {
  176.   char *p = pattern;
  177.   char *cp = current,*xp;
  178.   int leftcount = 1;
  179.   int commacount = 0;
  180.  
  181.   while(leftcount > 0) {        /* make sure braces match correctly */
  182.     switch(*p) {
  183.     case '{':                /* if a char is an open brace */
  184.       leftcount++;            /* count it */
  185.       break;
  186.     case '}':                /* likewise a close brace */
  187.       leftcount--;
  188.       break;
  189.     case ',':                /* a "," in the current set of braces*/
  190.       if (leftcount == 1)
  191.     commacount = 1;            /* note end of token */
  192.       break;
  193.     }
  194.     if (!leftcount || commacount || *p == '\0') { /* token ended */
  195.       strncpy(cp,pattern,p-pattern);    /* copy token */
  196.       cp[p-pattern] = '\0';        /* tie it off */
  197.       xp = p;                /* save pointer */
  198.       if (leftcount == 0) xp++;        /* if the close brace, pass it */
  199.       while(leftcount > 0) {        /* then scan to end of pattern */
  200.     if (*xp == '{') leftcount++;
  201.     else if (*xp == '}') leftcount--;
  202.     else if (*xp == '\0') break;
  203.     xp++;
  204.       }
  205.       strcat(cp,xp);            /* append the rest of the string */
  206.       return(p);            /* return pointer to end of token */
  207.     }
  208.     p++;                /* otherwise, keep traversing string */
  209.   }
  210. }
  211.  
  212. /*
  213.  * pattern match
  214.  * if partial, append a "*" to the pattern
  215.  * if *.* in msdos, then match
  216.  * otherwise, try to match
  217.  */
  218.  
  219. fmatch(string,pattern,partial) char *string,*pattern; int partial; {
  220.   int ret;
  221.   char temp[30];
  222.   char *pat = temp;
  223.   if (strlen(pattern)+2 > 29)
  224.       pat = (char *)malloc(strlen(pattern)+2);
  225.   strcpy(pat,pattern);
  226.   if (partial) strcat(pat,"*");
  227. #ifdef MSDOS
  228.   if (!strcmp(pat,"*.*")) 
  229.     ret = TRUE;
  230.   else
  231. #endif
  232.   ret = match(pat,string);
  233.   if (pat != temp)
  234.       free(pat);
  235.   return(ret);
  236. }
  237.  
  238.